/*
 *    <one line to give the program's name and a brief idea of what it does.>
 *    Copyright (C) <year>  <name of author>
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "RenderManager.h"

#include "RenderEngine.h"

#include "Map.h"
#include "IMapElement.h"
#include "TextureManager.h"

#include <cassert>
#include <MapManager.h>


static SingletonDestroyer<RenderManager> destroyer;


RenderManager::RenderManager()
{
   _renderEngine = RenderEngine::getInstance();
   assert(_renderEngine != NULL);
   
   _mapManager = MapManager::getInstance();
   assert(_mapManager != NULL);

   _textureManager = TextureManager::getInstance();
   assert(_textureManager != NULL);

   _xMinOrtho = _yMinOrtho = 0;
   _xMaxOrtho = _yMaxOrtho = 10;
}

RenderManager::~RenderManager()
{

}

void RenderManager::DrawMap(const Map & iMap) const
{
   const uint nbCol = iMap.getNbCol();
   const uint nbLine = iMap.getNbLine();
   
   const uint nbCells = nbCol * nbLine;

   quadrangle position;

   //Compute the size of an element
   float sizeOfElementX = (float)(_xMaxOrtho - _xMinOrtho) / (float)nbCol;
   float sizeOfElementY = (float)(_yMaxOrtho - _yMinOrtho) / (float)nbLine;

   //Compute the position of an element
   //The position corresponds to the middle of the sprite
   int curLine = -1;
   for(uint i = 0 ; i < nbCells ; ++i)
   {
      int curCol  = (int)(i % nbCol);
      if(curCol == 0)
         ++curLine;
      
      position.pointBL.x = position.pointTL.x = curCol * sizeOfElementX;
      position.pointBL.y = position.pointBR.y = curLine * sizeOfElementY;
      position.pointBR.x = position.pointTR.x = curCol * sizeOfElementX + sizeOfElementX;
      position.pointTL.y = position.pointTR.y = curLine * sizeOfElementY + sizeOfElementY;
      
      
      Draw(iMap[i], position);
   }

}

void RenderManager::Draw(const IMapElement*const iME, quadrangle& iPosition) const
{
   unsigned int texID;
   float2 texCoordBL, texCoordTL, texCoordTR, texCoordBR;
   
   _textureManager->getTexture(iME->getSpriteID(), iME->getTextureType(), texID, texCoordBL, texCoordTL, texCoordTR, texCoordBR);

   _renderEngine->drawSprite(texID, texCoordBL, texCoordTL, texCoordTR, texCoordBR, iPosition);

}


void RenderManager::Init() const
{
   assert(_renderEngine != NULL);
   
   _renderEngine->init();
}

void RenderManager::Resize(int iWidth, int iHeight) const
{
   assert(_renderEngine != NULL);
   
   _renderEngine->resize(iWidth, iHeight);
}


void RenderManager::DrawScene() const
{
   assert(_renderEngine != NULL);
   assert(_mapManager   != NULL);
   
   _renderEngine->BeginDraw();
   
   Map * currentMap = _mapManager->GetCurrentMap();
   assert(currentMap != NULL);
   
   DrawMap(*currentMap);
}

uint RenderManager::CreateTexture(unsigned char * iData, const int iWidth, const int iHeight) const
{
   assert(iData != NULL && iWidth > 0 && iHeight > 0);
   assert(_renderEngine != NULL);
   
   return _renderEngine->CreateTexture(iData, iWidth, iHeight);
}


